#include "descr_strat_parser.h"

#include <sstream>
#include "character.h"
#include "settlement_type.h"


using namespace std;


bool DescrStratParser::parse(string line)
{
	string token = popNextToken(line);
	if (token.compare("playable") == 0)
	{
		state = DescrStratParser::PLAYABLE;
	}
	else if (token.compare("nonplayable") == 0)
	{
		state = DescrStratParser::NONPLAYABLE;
	}
	else if (token.compare("end") == 0)
	{
		state = DescrStratParser::NONE;
	}
	else if (token.compare("resource") == 0)
	{
		string resourceID = popNextToken(line);
	}
	else if (token.compare("faction") == 0)
	{
		string factionID = popNextToken(line);
		parsingFaction = Faction::get(factionID);
	}
	else if (token.compare("denari") == 0)
	{
		string denari = popNextToken(line);
		istringstream(denari) >> parsingFaction->denari;
	}
	else if (token.compare("denari_kings_purse") == 0)
	{
		string denari_kings_purse = popNextToken(line);
		istringstream(denari_kings_purse) >> parsingFaction->kingsPurse;
	}
	else if (token.compare("settlement") == 0)
	{
		token = popNextToken(line);
		if (token.compare("castle") == 0)
		{
			parsingIsCastle = true;
		}
		else
		{
			parsingIsCastle = false;
		}
	}
	else if (token.compare("{") == 0)
	{
		if (state == NONE)
		{
			state = SETTLEMENT;
		}
		else if (state == SETTLEMENT)
		{
			state = BUILDING;
		}
	}
	else if (token.compare("}") == 0)
	{
		if (state == SETTLEMENT)
		{
			state = NONE;
		}
		else if (state == BUILDING)
		{
			state = SETTLEMENT;
		}
	}
	else if (token.compare("level") == 0)
	{
		parsingSettlementTypeID = popNextToken(line);
	}
	else if (token.compare("region") == 0)
	{
		if (state == SETTLEMENT)
		{
			string regionID = popNextToken(line);
			parsingRegion = Region::get(regionID);

			if (parsingIsCastle)
			{
				int level = SettlementType::get(parsingSettlementTypeID)->level;
				parsingSettlementTypeID = SettlementType::castles[level]->id;
			}
			parsingRegion->settlementTypeID = parsingSettlementTypeID;
			
			parsingFaction->regions.push_back(parsingRegion);
		}
	}
	else if (token.compare("population") == 0)
	{
		string population = popNextToken(line);
		istringstream(population) >> parsingRegion->population;
	}
	else if (token.compare("faction_creator") == 0)
	{
		string founderFactionID = popNextToken(line);
		parsingRegion->founderFactionID = founderFactionID;
	}
	else if (token.compare("character") == 0)
	{
		token = popNextToken(line, COMMA);
		if (token.compare(0, 11, "sub_faction") == 0)
		{
			token = popNextToken(line, COMMA);
		}

		parsingCharacter.reset(new Character());
		parsingCharacter->name = token;

		parsingFaction->characters.push_back(parsingCharacter);

		string typeName = popNextToken(line, COMMA);
		shared_ptr<Character::Type> type = Character::Type::get(typeName);
		if (type.get() == NULL)
		{
			cout << "type is null";
		}
		parsingCharacter->type = type;

		popNextToken(line); // sex

		token = popNextToken(line);
		if (token.compare("leader") == 0)
		{
			token = popNextToken(line);
		}
		else if (token.compare("heir") == 0)
		{
			token = popNextToken(line);
		}

		if (token.compare("age") == 0)
		{
			istringstream buffer(popNextToken(line));
			buffer >> parsingCharacter->age;			
		}

		token = popNextToken(line);
		if (token.compare("x") == 0)
		{
			istringstream buffer(popNextToken(line));
			buffer >> parsingCharacter->x;			
		}

		token = popNextToken(line);
		if (token.compare("y") == 0)
		{
			istringstream buffer(popNextToken(line));
			buffer >> parsingCharacter->y;			
		}
	}
	else
	{
		switch (state)
		{
			case DescrStratParser::PLAYABLE:
			{
				shared_ptr<Faction> faction = Faction::get(token);
				if (faction.get() != NULL)
				{
					faction->isPlayable = true;
				}
			}
			break;

			case DescrStratParser::NONPLAYABLE:
			{
				shared_ptr<Faction> faction = Faction::get(token);
				if (faction.get() != NULL)
				{
					faction->isPlayable = false;
				}
			}
			break;
		}
	}

	return true;
}